home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / dflat_r_.arc / TEXTBOX.C < prev    next >
Text File  |  1991-10-02  |  18KB  |  730 lines

  1. /* ------------- textbox.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <dos.h>
  7. #include "dflat.h"
  8.  
  9. #ifdef INCLUDE_SCROLLBARS
  10. static void ComputeWindowTop(WINDOW);
  11. static void ComputeWindowLeft(WINDOW);
  12. static int ComputeVScrollBox(WINDOW);
  13. static int ComputeHScrollBox(WINDOW);
  14. static void MoveScrollBox(WINDOW, int);
  15. #endif
  16. static char *GetTextLine(WINDOW, int);
  17.  
  18. #ifdef INCLUDE_SCROLLBARS
  19. int VSliding;
  20. int HSliding;
  21. #endif
  22.  
  23. int TextBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  24. {
  25. #ifdef INCLUDE_SCROLLBARS
  26.     int    mx = (int) p1 - GetLeft(wnd);
  27.     int    my = (int) p2 - GetTop(wnd);
  28. #endif
  29.     switch (msg)    {
  30.         case CREATE_WINDOW:
  31.             wnd->HScrollBox = wnd->VScrollBox = TRUE;
  32.             ClearTextPointers(wnd);
  33.             break;
  34.         case ADDTEXT:    {
  35.             /* ======== need to assure that length !> 64K ======= */
  36.             int adln = strlen((char *)p1);
  37.             if (wnd->text != NULL)    {
  38.                 int txln = strlen(wnd->text);
  39.                 if (txln+adln > wnd->textlen)    {
  40.                     wnd->text = realloc(wnd->text, txln+adln+2);
  41.                     wnd->textlen = txln+adln;
  42.                 }
  43.             }
  44.             else    {
  45.                 if ((wnd->text = malloc(adln+2)) != NULL)
  46.                     *wnd->text = '\0';
  47.                 wnd->textlen = adln+1;
  48.             }
  49.             if (wnd->text != NULL)    {
  50.                 strcat(wnd->text, (char*) p1);
  51.                 strcat(wnd->text, "\n");
  52.                 BuildTextPointers(wnd);
  53.             }
  54.             break;
  55.         }
  56.         case SETTEXT:    {
  57.             char *cp;
  58.             unsigned int len;
  59.             cp = (void *) p1;
  60.             len = strlen(cp)+1;
  61.             if (wnd->text == NULL || wnd->textlen < len)    {
  62.                 wnd->textlen = len;
  63.                 if ((wnd->text = realloc(wnd->text, len)) == NULL)
  64.                     break;
  65.             }
  66.             strcpy(wnd->text, cp);
  67.             BuildTextPointers(wnd);
  68.             break;
  69.         }
  70.         case CLEARTEXT:
  71.             if (wnd->text != NULL)
  72.                 free(wnd->text);
  73.             wnd->text = NULL;
  74.             wnd->textlen = 0;
  75.             wnd->wlines = 0;
  76.             wnd->textwidth = 0;
  77.             wnd->wtop = wnd->wleft = 0;
  78.             ClearBlock(wnd);
  79.             ClearTextPointers(wnd);
  80.             break;
  81.         case KEYBOARD:
  82. #ifdef INCLUDE_SYSTEM_MENUS
  83.             if (WindowMoving || WindowSizing)
  84.                 break;
  85. #endif
  86.             switch ((int) p1)    {
  87.                 case UP:
  88.                     if (wnd->wtop)
  89.                         SendMessage(wnd, SCROLL, FALSE, 0);
  90.                     return TRUE;
  91.                 case DN:
  92.                     if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)
  93.                         SendMessage(wnd, SCROLL, TRUE, 0);
  94.                     return TRUE;
  95.                 case FWD:
  96.                     SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  97.                     return TRUE;
  98.                 case BS:
  99.                     SendMessage(wnd, HORIZSCROLL, FALSE, 0);
  100.                     return TRUE;
  101.                 case PGUP:
  102.                     if (wnd->wtop)    {
  103.                         wnd->wtop -= ClientHeight(wnd);
  104.                         if (wnd->wtop < 0)
  105.                             wnd->wtop = 0;
  106.                         SendMessage(wnd, PAINT, 0, 0);
  107.                         return TRUE;
  108.                     }
  109.                     return TRUE;
  110.                 case PGDN:
  111.                     if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)    {
  112.                         wnd->wtop += ClientHeight(wnd);
  113.                         if (wnd->wtop > wnd->wlines-ClientHeight(wnd))
  114.                             wnd->wtop = wnd->wlines-ClientHeight(wnd);
  115.                         SendMessage(wnd, PAINT, 0, 0);
  116.                         return TRUE;
  117.                     }
  118.                     return TRUE;
  119.                 case CTRL_PGUP:
  120.                     if (wnd->wleft)    {
  121.                         wnd->wleft -= ClientWidth(wnd);
  122.                         if (wnd->wleft < 0)
  123.                             wnd->wleft = 0;
  124.                         SendMessage(wnd, PAINT, 0, 0);
  125.                         return TRUE;
  126.                     }
  127.                     return TRUE;
  128.                 case CTRL_PGDN:
  129.                     if (wnd->wleft+ClientWidth(wnd) < wnd->textwidth)    {
  130.                         wnd->wleft += ClientWidth(wnd);
  131.                         if (wnd->wleft > wnd->textwidth-ClientWidth(wnd))
  132.                             wnd->wleft = wnd->textwidth-ClientWidth(wnd);
  133.                         SendMessage(wnd, PAINT, 0, 0);
  134.                         return TRUE;
  135.                     }
  136.                     return TRUE;
  137.                 case HOME:
  138.                     if (wnd->wtop || wnd->wleft)    {
  139.                         wnd->wtop = wnd->wleft = 0;
  140.                         SendMessage(wnd, PAINT, 0, 0);
  141.                     }
  142.                     return TRUE;
  143.                 case END:
  144.                     if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)    {
  145.                         wnd->wtop = wnd->wlines-ClientHeight(wnd);
  146.                         wnd->wleft = 0;
  147.                         SendMessage(wnd, PAINT, 0, 0);
  148.                     }
  149.                     return TRUE;
  150.                 default:
  151.                     break;
  152.             }
  153.             break;
  154.         case LEFT_BUTTON:
  155. #ifdef INCLUDE_SYSTEM_MENUS
  156.             if (WindowSizing || WindowMoving)
  157.                 return FALSE;
  158. #endif
  159. #ifdef INCLUDE_SCROLLBARS
  160.             if (TestAttribute(wnd, VSCROLLBAR) && mx == WindowWidth(wnd)-1)    {
  161.  
  162.                 /* -------- in the right border ------- */
  163.                 if (my == 0 || my == ClientHeight(wnd)+1)
  164.                     /* ------ above or below the scroll bar ---- */
  165.                     break;
  166.  
  167.                 if (my == 1)    {
  168.                     /* -------- top scroll button --------- */
  169.                     SendMessage(wnd, SCROLL, FALSE, 0);
  170.                     return TRUE;
  171.                 }
  172.                 if (my == ClientHeight(wnd))    {
  173.                     /* -------- bottom scroll button --------- */
  174.                     SendMessage(wnd, SCROLL, TRUE, 0);
  175.                     return TRUE;
  176.                 }
  177.  
  178.                 /* ---------- in the scroll bar ----------- */
  179.                 if (!VSliding && my-1 == wnd->VScrollBox)    {
  180.                     RECT rc;
  181.                     VSliding = TRUE;
  182.                     rc.lf = rc.rt = GetRight(wnd);
  183.                     rc.tp = GetTop(wnd)+2;
  184.                     rc.bt = GetBottom(wnd)-2;
  185.                     SendMessage(NULLWND, MOUSE_TRAVEL, (PARAM) &rc, 0);
  186.                     return TRUE;
  187.                 }
  188.  
  189.                 if (my-1 < wnd->VScrollBox)    {
  190.                     SendMessage(wnd, KEYBOARD, PGUP, 0);
  191.                     return TRUE;
  192.                 }
  193.                 if (my-1 > wnd->VScrollBox)    {
  194.                     SendMessage(wnd, KEYBOARD, PGDN, 0);
  195.                     return TRUE;
  196.                 }
  197.             }
  198.             if (TestAttribute(wnd, HSCROLLBAR) && my == WindowHeight(wnd)-1) {
  199.                 /* -------- in the bottom border ------- */
  200.                 if (mx == 0 || my == ClientWidth(wnd)+1)
  201.                     /* ------  outside the scroll bar ---- */
  202.                     break;
  203.  
  204.                 if (mx == 1)    {
  205.                     SendMessage(wnd, HORIZSCROLL, FALSE, 0);
  206.                     return TRUE;
  207.                 }
  208.                 if (mx == WindowWidth(wnd)-2)    {
  209.                     SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  210.                     return TRUE;
  211.                 }
  212.  
  213.                 if (!HSliding && mx-1 == wnd->HScrollBox)    {
  214.                     RECT rc;
  215.                     rc.lf = GetLeft(wnd)+2;
  216.                     rc.rt = GetRight(wnd)-2;
  217.                     rc.tp = rc.bt = GetBottom(wnd);
  218.                     SendMessage(NULLWND, MOUSE_TRAVEL, (PARAM) &rc, 0);
  219.                     HSliding = TRUE;
  220.                     return TRUE;
  221.                 }
  222.  
  223.                 if (mx-1 < wnd->HScrollBox)    {
  224.                     SendMessage(wnd, KEYBOARD, CTRL_PGUP, 0);
  225.                     return TRUE;
  226.                 }
  227.                 if (mx-1 > wnd->HScrollBox)    {
  228.                     SendMessage(wnd, KEYBOARD, CTRL_PGDN, 0);
  229.                     return TRUE;
  230.                 }
  231.             }
  232.             break;
  233.         case MOUSE_MOVED:
  234.             if (VSliding)    {
  235.                 if (my-1 != wnd->VScrollBox)    {
  236.                     foreground = FrameForeground(wnd);
  237.                     background = FrameBackground(wnd);
  238.                     PutWindowChar(wnd, WindowWidth(wnd)-1, wnd->VScrollBox+1,
  239.                         SCROLLBARCHAR);
  240.                     wnd->VScrollBox = my-1;
  241.                     PutWindowChar(wnd, WindowWidth(wnd)-1, my, SCROLLBOXCHAR);
  242.                 }
  243.                 return TRUE;
  244.             }
  245.             if (HSliding)    {
  246.                 if (mx-1 != wnd->HScrollBox)    {
  247.                     foreground = FrameForeground(wnd);
  248.                     background = FrameBackground(wnd);
  249.                     PutWindowChar(wnd, wnd->HScrollBox+1, WindowHeight(wnd)-1,
  250.                         SCROLLBARCHAR);
  251.                     wnd->HScrollBox = mx-1;
  252.                     PutWindowChar(wnd, mx, WindowHeight(wnd)-1,SCROLLBOXCHAR);
  253.                 }
  254.                 return TRUE;
  255.             }
  256.             break;
  257.         case BUTTON_RELEASED:
  258.             if (HSliding || VSliding)    {
  259.                 RECT rc;
  260.                 rc.lf = rc.tp = 0;
  261.                 rc.rt = SCREENWIDTH-1;
  262.                 rc.bt = SCREENHEIGHT-1;
  263.                 SendMessage(NULLWND, MOUSE_TRAVEL, (PARAM) &rc, 0);
  264.                 VSliding ? ComputeWindowTop(wnd) : ComputeWindowLeft(wnd);
  265.                 SendMessage(wnd, PAINT, 0, 0);
  266.                 SendMessage(wnd, KEYBOARD_CURSOR, 0, 0);
  267.                 VSliding = HSliding = FALSE;
  268.             }
  269.             break;
  270. #endif
  271.         case SCROLL:
  272.             if (p1)    {
  273.                 if (wnd->wtop+ClientHeight(wnd) >= wnd->wlines)
  274.                     return FALSE;
  275.                 wnd->wtop++;
  276.             }
  277.             else    {
  278.                 if (wnd->wtop == 0)
  279.                     return FALSE;
  280.                 --wnd->wtop;
  281.             }
  282.             if (isVisible(wnd) && (int) p2 == FALSE)    {
  283.                 RECT rc;
  284.                 rc = ClipRectangle(wnd, ClientRect(wnd));
  285.                 if (ValidRect(rc))    {
  286.                     scroll_window(wnd, rc, (int)p1);
  287.                     if (!(int)p1)
  288.                         WriteTextLine(wnd, NULL, wnd->wtop, FALSE);
  289.                     else    {
  290.                         int y = RectBottom(rc)-GetClientTop(wnd);
  291.                         WriteTextLine(wnd, NULL,
  292.                             wnd->wtop+y, FALSE);
  293.                     }
  294.                 }
  295. #ifdef INCLUDE_SCROLLBARS
  296.                 if (TestAttribute(wnd, VSCROLLBAR))    {
  297.                     int vscrollbox = ComputeVScrollBox(wnd);
  298.                     if (vscrollbox != wnd->VScrollBox)
  299.                         MoveScrollBox(wnd, vscrollbox);
  300.                 }
  301. #endif
  302.             }
  303.             return TRUE;
  304.         case HORIZSCROLL:
  305.             if (p1)    {
  306.                 if (wnd->wleft + ClientWidth(wnd)-1 >= wnd->textwidth)
  307.                     return FALSE;
  308.                 wnd->wleft++;
  309.             }
  310.             else    {
  311.                 if (wnd->wleft == 0)
  312.                     return FALSE;
  313.                 --wnd->wleft;
  314.             }
  315.             if (isVisible(wnd) && (int) p2 == FALSE)
  316.                 SendMessage(wnd, PAINT, 0, 0);
  317.             return TRUE;
  318.         case PAINT:
  319.             if (isVisible(wnd) && wnd->wlines)    {
  320.                 RECT rc, rcc;
  321.                 int y;
  322.                 char blankline[201];
  323.  
  324.                 if ((RECT *)p1 == NULL)
  325.                     rc = RelativeWindowRect(wnd, WindowRect(wnd));
  326.                 else
  327.                     rc = *(RECT *)p1;
  328.  
  329.                 if (TestAttribute(wnd, HASBORDER) &&
  330.                         RectRight(rc) >= WindowWidth(wnd)-1)    {
  331.                     if (RectLeft(rc) >= WindowWidth(wnd)-1)
  332.                         return TRUE;
  333.                     RectRight(rc) = WindowWidth(wnd)-2;
  334.                 }
  335.  
  336.                 rcc = AdjustRectangle(wnd, rc);
  337.                 memset(blankline, ' ', SCREENWIDTH);
  338.                 blankline[RectRight(rcc)+1] = '\0';
  339.  
  340.                 for (y = RectTop(rc); y <= RectBottom(rc); y++)    {
  341.                     int yy;
  342.                     if (TestAttribute(wnd, HASBORDER | HASTITLEBAR))    {
  343.                         if (y < TopBorderAdj(wnd))
  344.                             continue;
  345.                         if (y > WindowHeight(wnd)-2)
  346.                             continue;
  347.                     }
  348.                     yy = y-TopBorderAdj(wnd);
  349.                     if (yy < wnd->wlines-wnd->wtop)
  350.                         WriteTextLine(wnd, &rc, yy+wnd->wtop, FALSE);
  351.                     else    {
  352.                         SetStandardColor(wnd);
  353.                         writeline(wnd, blankline+RectLeft(rcc),
  354.                                 RectLeft(rcc)+1, y, FALSE);
  355.                     }
  356.                 }
  357. #ifdef INCLUDE_SCROLLBARS
  358.                 if (TestAttribute(wnd, VSCROLLBAR | HSCROLLBAR))    {
  359.                     int hscrollbox = ComputeHScrollBox(wnd);
  360.                     int vscrollbox = ComputeVScrollBox(wnd);
  361.                     if (hscrollbox != wnd->HScrollBox ||
  362.                             vscrollbox != wnd->VScrollBox)    {
  363.                         wnd->HScrollBox = hscrollbox;
  364.                         wnd->VScrollBox = vscrollbox;
  365.                         SendMessage(wnd, BORDER, p1, 0);
  366.                     }
  367.                 }
  368. #endif
  369.                 return FALSE;
  370.             }
  371.             break;
  372.         case CLOSE_WINDOW:
  373.             SendMessage(wnd, CLEARTEXT, 0, 0);
  374.             if (wnd->TextPointers != NULL)    {
  375.                 free(wnd->TextPointers);
  376.                 wnd->TextPointers = NULL;
  377.             }
  378.             break;
  379.         default:
  380.             break;
  381.     }
  382.     return BaseWndProc(TEXTBOX, wnd, msg, p1, p2);
  383. }
  384.  
  385. #ifdef INCLUDE_SCROLLBARS
  386. static int ComputeVScrollBox(WINDOW wnd)
  387. {
  388.     int pagelen = wnd->wlines - ClientHeight(wnd);
  389.     int barlen = ClientHeight(wnd)-2;
  390.     int lines_tick;
  391.     int vscrollbox;
  392.  
  393.     if (pagelen < 1 || barlen < 1)
  394.         vscrollbox = 1;
  395.     else    {
  396.         if (pagelen > barlen)
  397.             lines_tick = pagelen / barlen;
  398.         else
  399.             lines_tick = barlen / pagelen;
  400.         vscrollbox = 1 + (wnd->wtop / lines_tick);
  401.         if (vscrollbox > ClientHeight(wnd)-2 ||
  402.                 wnd->wtop + ClientHeight(wnd) >= wnd->wlines)
  403.             vscrollbox = ClientHeight(wnd)-2;
  404.     }
  405.     return vscrollbox;
  406. }
  407.  
  408. static void ComputeWindowTop(WINDOW wnd)
  409. {
  410.     int pagelen = wnd->wlines - ClientHeight(wnd);
  411.     if (wnd->VScrollBox == 0)
  412.         wnd->wtop = 0;
  413.     else if (wnd->VScrollBox == ClientHeight(wnd)-2)
  414.         wnd->wtop = pagelen;
  415.     else    {
  416.         int barlen = ClientHeight(wnd)-2;
  417.         int lines_tick;
  418.  
  419.         if (pagelen > barlen)
  420.             lines_tick = pagelen / barlen;
  421.         else
  422.             lines_tick = barlen / pagelen;
  423.         wnd->wtop = (wnd->VScrollBox-1) * lines_tick;
  424.         if (wnd->wtop + ClientHeight(wnd) > wnd->wlines)
  425.             wnd->wtop = pagelen;
  426.     }
  427.     if (wnd->wtop < 0)
  428.         wnd->wtop = 0;
  429. }
  430.  
  431. static int ComputeHScrollBox(WINDOW wnd)
  432. {
  433.     int pagewidth = wnd->textwidth - ClientWidth(wnd);
  434.     int barlen = ClientWidth(wnd)-2;
  435.     int chars_tick;
  436.     int hscrollbox;
  437.  
  438.     if (pagewidth < 1 || barlen < 1)
  439.         hscrollbox = 1;
  440.     else     {
  441.         if (pagewidth > barlen)
  442.             chars_tick = pagewidth / barlen;
  443.         else
  444.             chars_tick = barlen / pagewidth;
  445.         hscrollbox = 1 + (wnd->wleft / chars_tick);
  446.         if (hscrollbox > ClientWidth(wnd)-2 ||
  447.                 wnd->wleft + ClientWidth(wnd) >= wnd->textwidth)
  448.             hscrollbox = ClientWidth(wnd)-2;
  449.     }
  450.     return hscrollbox;
  451. }
  452.  
  453. static void ComputeWindowLeft(WINDOW wnd)
  454. {
  455.     int pagewidth = wnd->textwidth - ClientWidth(wnd);
  456.  
  457.     if (wnd->HScrollBox == 0)
  458.         wnd->wleft = 0;
  459.     else if (wnd->HScrollBox == ClientWidth(wnd)-2)
  460.         wnd->wleft = pagewidth;
  461.     else    {
  462.         int barlen = ClientWidth(wnd)-2;
  463.         int chars_tick;
  464.  
  465.         if (pagewidth > barlen)
  466.             chars_tick = pagewidth / barlen;
  467.         else
  468.             chars_tick = barlen / pagewidth;
  469.         wnd->wleft = (wnd->HScrollBox-1) * chars_tick;
  470.         if (wnd->wleft + ClientWidth(wnd) > wnd->textwidth)
  471.             wnd->wleft = pagewidth;
  472.     }
  473.     if (wnd->wleft < 0)
  474.         wnd->wleft = 0;
  475. }
  476. #endif
  477.  
  478. static char *GetTextLine(WINDOW wnd, int selection)
  479. {
  480.     char *line;
  481.     int len = 0;
  482.     char *cp, *cp1;
  483.     cp = cp1 = TextLine(wnd, selection);
  484.     while (*cp && *cp != '\n')    {
  485.         len++;
  486.         cp++;
  487.     }
  488.     line = malloc(len+6);
  489.     if (line != NULL)    {
  490.         memmove(line, cp1, len);
  491.         line[len] = '\0';
  492.     }
  493.     return line;
  494. }
  495.  
  496. void WriteTextLine(WINDOW wnd, RECT *rcc, int y, int reverse)
  497. {
  498.     int len = 0;
  499.     int dif = 0;
  500.     unsigned char *line;
  501.     RECT rc;
  502.     unsigned char *lp, *svlp;
  503.     int lnlen;
  504.     int i;
  505.     int trunc = FALSE;
  506.  
  507.     if (y < wnd->wtop || y >= wnd->wtop+ClientHeight(wnd))
  508.         return;
  509.  
  510.     if (rcc == NULL)    {
  511.         rc = RelativeWindowRect(wnd, WindowRect(wnd));
  512.         if (TestAttribute(wnd, HASBORDER) &&
  513.                 RectRight(rc) >= WindowWidth(wnd)-1)
  514.             RectRight(rc) = WindowWidth(wnd)-2;
  515.     }
  516.     else
  517.         rc = *rcc;
  518.  
  519.     if (RectLeft(rc) >= WindowWidth(wnd)-1)
  520.         return;
  521.     if (RectRight(rc) == 0)
  522.         return;
  523.  
  524.     rc = AdjustRectangle(wnd, rc);
  525.  
  526.     lp = svlp = GetTextLine(wnd, y);
  527.     lnlen = LineLength(lp);
  528.  
  529.     /* -------- insert block color change controls ------- */
  530.     if (BlockMarked(wnd))    {
  531.         int bbl = wnd->BlkBegLine;
  532.         int bel = wnd->BlkEndLine;
  533.         int bbc = wnd->BlkBegCol;
  534.         int bec = wnd->BlkEndCol;
  535.         int by = y;
  536.  
  537.         if (bbl > bel)    {
  538.             swap(bbl, bel);
  539.             swap(bbc, bec);
  540.         }
  541.         if (bbl == bel && bbc > bec)
  542.             swap(bbc, bec);
  543.  
  544.         if (by >= bbl && by <= bel)    {
  545.             /* ------ the block includes this line ----- */
  546.             int blkbeg = 0;
  547.             int blkend = lnlen;
  548.             if (!(by > bbl && by < bel))    {
  549.                 /* --- the entire line is not in the block --- */
  550.                 if (by == bbl)
  551.                     /* ---- the block begins on this line ---- */
  552.                     blkbeg = bbc;
  553.                 if (by == bel)
  554.                     /* ---- the block ends on this line ---- */
  555.                     blkend = bec;
  556.             }
  557.             memmove(lp+blkend+1, lp+blkend, strlen(lp+blkend)+1);
  558.             lp[blkend] = RESETCOLOR;
  559.             memmove(lp+blkbeg+3, lp+blkbeg, strlen(lp+blkbeg)+1);
  560.             lp[blkbeg] = CHANGECOLOR;
  561.             SetReverseColor(wnd);
  562.             lp[blkbeg+1] = foreground | 0x80;
  563.             lp[blkbeg+2] = background | 0x80;
  564.             lnlen += 4;
  565.         }
  566.     }
  567.  
  568.     for (i = 0; i < wnd->wleft+3; i++)    {
  569.         if (*(lp+i) == '\0')
  570.             break;
  571.         if (*(unsigned char *)(lp + i) == RESETCOLOR)
  572.             break;
  573.     }
  574.     if (*(lp+i) && i < wnd->wleft+3)    {
  575.         if (wnd->wleft+4 > lnlen)
  576.             trunc = TRUE;
  577.         else 
  578.             lp += 4;
  579.     }
  580.     else     {
  581.         for (i = 0; i < wnd->wleft; i++)    {
  582.             if (*(lp+i) == '\0')
  583.                 break;
  584.             if (*(unsigned char *)(lp + i) == CHANGECOLOR)    {
  585.                 *(lp+wnd->wleft+2) = *(lp+i+2);
  586.                 *(lp+wnd->wleft+1) = *(lp+i+1);
  587.                 *(lp+wnd->wleft) = *(lp+i);
  588.                 break;
  589.             }
  590.         }
  591.     }
  592.  
  593.     if ((line = malloc(200)) != NULL)    {
  594.         if (!trunc)    {
  595.             if (lnlen < wnd->wleft)
  596.                 lnlen = 0;
  597.             else
  598.                 lp += wnd->wleft;
  599.  
  600.  
  601.             if (y-wnd->wtop < RectTop(rc) || y-wnd->wtop > RectBottom(rc))
  602.                 return;
  603.  
  604.             if (lnlen > RectLeft(rc))    {
  605.                 int ct = RectLeft(rc);
  606.                 char *initlp = lp;
  607.                 while (ct)    {
  608.                     if (*(unsigned char *)lp == CHANGECOLOR)
  609.                         lp += 3;
  610.                     else if (*(unsigned char *)lp == RESETCOLOR)
  611.                         lp++;
  612.                     else
  613.                         lp++, --ct;
  614.                 }
  615.                 if (RectLeft(rc))    {
  616.                     char *lpp = lp;
  617.                     while (*lpp)    {
  618.                         if (*(unsigned char *)lpp == CHANGECOLOR)
  619.                             break;
  620.                         if (*(unsigned char *)lpp == RESETCOLOR)    {
  621.                             lpp = lp;
  622.                             while (lpp >= initlp)    {
  623.                                 if (*(unsigned char *)lpp == CHANGECOLOR)    {
  624.                                     lp -= 3;
  625.                                     memmove(lp,lpp,3);
  626.                                     break;
  627.                                 }
  628.                                 --lpp;
  629.                             }
  630.                             break;
  631.                         }
  632.                         lpp++;
  633.                     }
  634.                 }
  635.                 lnlen = LineLength(lp);
  636.                 len = min(lnlen, RectWidth(rc));
  637.                 dif = strlen(lp) - lnlen;
  638.                 len += dif;
  639.                 if (len > 0)
  640.                     strncpy(line, lp, len);
  641.             }
  642.         }
  643.  
  644.         while (len < RectWidth(rc)+dif)
  645.             line[len++] = ' ';
  646.         line[len] = '\0';
  647.  
  648.         dif = 0;
  649.         if (reverse)    {
  650.             char *cp = line;
  651.             SetReverseColor(wnd);
  652.             while ((cp = strchr(cp, CHANGECOLOR)) != NULL)    {
  653.                 cp += 2;
  654.                 *cp++ = background | 0x80;
  655.             }
  656.             if (*(unsigned char *)line == CHANGECOLOR)
  657.                 dif = 3;
  658.         }
  659.         else
  660.             SetStandardColor(wnd);
  661.         writeline(wnd, line+dif,
  662.                     RectLeft(rc)+BorderAdj(wnd),
  663.                         y-wnd->wtop+TopBorderAdj(wnd), FALSE);
  664.         if (svlp != NULL)
  665.             free(svlp);
  666.         free(line);
  667.     }
  668. }
  669.  
  670. void SetAnchor(WINDOW wnd, int mx, int my)
  671. {
  672.     if (BlockMarked(wnd))    {
  673.         ClearBlock(wnd);
  674.         SendMessage(wnd, PAINT, 0, 0);
  675.     }
  676.     /* ------ set the anchor ------ */
  677.     wnd->BlkBegLine = wnd->BlkEndLine = my;
  678.     wnd->BlkBegCol = wnd->BlkEndCol = mx;
  679. }
  680.  
  681. void ClearTextPointers(WINDOW wnd)
  682. {
  683.     wnd->TextPointers = realloc(wnd->TextPointers, sizeof(int));
  684.     if (wnd->TextPointers != NULL)
  685.         *(wnd->TextPointers) = 0;
  686. }
  687.  
  688. #define INITLINES 100
  689.  
  690. void BuildTextPointers(WINDOW wnd)
  691. {
  692.     char *cp = wnd->text, *cp1;
  693.     int incrs = INITLINES;
  694.     int off;
  695.     wnd->textwidth = wnd->wlines = 0;
  696.     while (*cp)    {
  697.         if (incrs == INITLINES)    {
  698.             incrs = 0;
  699.             wnd->TextPointers = realloc(wnd->TextPointers,
  700.                     (wnd->wlines + INITLINES) * sizeof(int));
  701.             if (wnd->TextPointers == NULL)
  702.                 break;
  703.         }
  704.         off = (unsigned int) (cp - wnd->text);
  705.         *((wnd->TextPointers) + wnd->wlines) = off;
  706.         wnd->wlines++;
  707.         incrs++;
  708.         cp1 = cp;
  709.         while (*cp && *cp != '\n')
  710.             cp++;
  711.         wnd->textwidth = max(wnd->textwidth,
  712.                         (unsigned int) (cp - cp1));
  713.         if (*cp)
  714.             cp++;
  715.     }
  716. }
  717.  
  718. #ifdef INCLUDE_SCROLLBARS
  719. static void MoveScrollBox(WINDOW wnd, int vscrollbox)
  720. {
  721.     foreground = FrameForeground(wnd);
  722.     background = FrameBackground(wnd);
  723.     PutWindowChar(wnd, WindowWidth(wnd)-1,
  724.             wnd->VScrollBox+1, SCROLLBARCHAR);
  725.     PutWindowChar(wnd, WindowWidth(wnd)-1,
  726.             vscrollbox+1, SCROLLBOXCHAR);
  727.     wnd->VScrollBox = vscrollbox;
  728. }
  729. #endif
  730.